#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2024/5/22 16:02
# @Author  : liutianwei
# @File    : CpuMemAbilityFixture.py
# @Software: PyCharm
import tempfile
import time

import pytest
from _pytest.fixtures import SubRequest
import subprocess
import threading
import allure
import os
from pyecharts import options as opts
from pyecharts.charts import Line


@pytest.fixture(autouse=False, scope="class", name="CpuMemCalculate")
def record_cpu_mem_fixture(request: SubRequest):
    from conftest import cmder
    # 创建cpu_mem文件夹
    cpu_mem_dir = os.path.join(cmder.suite_dir, 'cpu_mem')
    os.mkdir(cpu_mem_dir)
    # 开始记录cpu与内存的占用率
    # 设置结束标志变量
    cmder.global_tag = False
    thread = threading.Thread(target=cpu_recorder, args=(cmder,))
    thread.start()

    yield
    cmder.global_tag = True
    if thread.is_alive():
        thread.join()
    # 设置内存保存list
    mem_group = {
        "LCSEngine": [],
        "AIBSService": [],
        "pasr_engine": []
    }
    cpu_group = {
        "LCSEngine": [],
        "AIBSService": [],
        "pasr_engine": []
    }
    mem_data = []
    # 开始计算cpu占用率
    with open(os.path.join(cpu_mem_dir, "cpu_mem.txt"), "r", encoding="utf-8") as f:
        lines = f.readlines()
        process_mem = []
        for line in lines:
            line = line.strip()
            if not line:
                continue
            if "LCSEngine" in line or "AIBSService" in line or "pasr_engine" in line:
                process_list = line.split()
                process_mem.append(process_list)
                if process_list[-1].rstrip('\n') in mem_group.keys():
                    mem_source_data = process_list[5]
                    if mem_source_data.endswith("g"):
                        mem_data = float(mem_source_data[-1]) * 1024
                    elif mem_source_data.endswith("m"):
                        mem_data = float(mem_source_data[-1])
                    else:
                        mem_data = float(mem_source_data) / 1024
                    mem_group[process_list[-1].rstrip('\n')].append(round(mem_data))
                    cpu_group[process_list[-1].rstrip('\n')].append(process_list[-4])
    if cmder.case_header.cpuMemTag.value == 'ALL' or cmder.case_header.cpuMemTag.value == 'MEM':
        mem_html_path = os.path.join(request.cls.conveyor.suite_dir, "cpu_mem/mem.html")
        graw_ui(data=mem_group, title="内存占用曲线", name=mem_html_path)
        allure.attach.file(source=mem_html_path, name="mem", attachment_type=allure.attachment_type.HTML)
        with open(os.path.join(cpu_mem_dir, "mem.txt"), "w", encoding="utf-8") as f_men:
            f_men.write(f"PID\t\tUSER\t\tRES\t\tMEM\t\tCOMMAND\n")
            for line in process_mem:
                f_men.write(f"{line[0]}\t\t{line[1]}\t\t{line[5]}\t\t{line[-3]}\t\t{line[-1]}\n")
    if cmder.case_header.cpuMemTag.value == 'ALL' or cmder.case_header.cpuMemTag.value == 'CPU':
        cpu_html_path = os.path.join(request.cls.conveyor.suite_dir, "cpu_mem/cpu.html")
        graw_ui(data=cpu_group, title="cpu占用曲线", name=cpu_html_path)
        allure.attach.file(source=cpu_html_path, name="cpu", attachment_type=allure.attachment_type.HTML)
        with open(os.path.join(cpu_mem_dir, "cpu.txt"), "w", encoding="utf-8") as f_cpu:
            f_cpu.write(f"PID\t\tUSER\t\tCPU\t\tCOMMAND\n")
            for line in process_mem:
                f_cpu.write(f"{line[0]}\t\t{line[1]}\t\t{line[-4]}\t\t{line[-1]}\n")

def cpu_recorder(cmder):
    while not cmder.global_tag:
        cpu_command = f'top -w 512 -b -n 1 -p {cmder.lcs_pid},{cmder.speech_pid},{cmder.aibs_pid}'
        top_process = subprocess.Popen(cpu_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        stdout_data, stderr_data = top_process.communicate()
        with open(os.path.join(cmder.suite_dir, "cpu_mem/cpu_mem.txt"), "a", encoding="utf-8") as f:
            f.write(stdout_data.decode())
            f.close()
        time.sleep(0.5)


def graw_ui(data, name, title):
    line = Line(
        init_opts=opts.InitOpts(width="100%", height="900px")
    )

    # 添加第一个数据系列
    for process, datas in data.items():
        data_length = len(datas)
        line.add_xaxis([i for i in range(data_length)])
        line.add_yaxis(
            series_name=process,
            y_axis=datas,
            is_smooth=True,
            markline_opts=opts.MarkLineOpts(data=[opts.MarkLineItem(type_="average")]),
            markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max")])
        )
    # 设置全局配置项
    line.set_global_opts(title_opts=opts.TitleOpts(title=title))
    # 生成HTML文件并保存到本地
    line.render(name)
